home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / misc / emu / Apex-src.lha / DISASM.XPL < prev    next >
Text File  |  2001-09-30  |  21KB  |  966 lines

  1. \DISASM.XPL    APR-10-87
  2. \68000/68881 Disassembler
  3. \ by Loren Blaney
  4. \
  5. \REVISION HISTORY:
  6. \DEC-26-85, Added 68881 instructions, L.B.
  7. \MAR-03-86, Modified for 32-bit XPL, L.B.
  8. \AUG-23-86, Fixed miscellaneous bugs, L.B.
  9. \OCT-18-86, Modified for new compiler.
  10. \APR-10-87, Changed string convention, fixed MUL and DIV, and PC relative
  11. \ addresses.
  12. \
  13. \NOTES:
  14. \The output is buffered (in LINBUF) and is divided into fields:
  15. \          1         2         3         4       
  16. \01234567890123456789012345678901234567890123456789
  17. \ASCII       PC         HEX                   TEXT (MNEMONICS)
  18. \AABBCCDDEE  00000000:  00001111222233334444  TEXT..........
  19. \
  20. \(Contrary to what Motorola claims, the 68000 is not very symmetrical.)
  21.  
  22. \WARNING:
  23. \The size extensions are used haphazardly.
  24. \The FDBcc instructions don't consistently display the target branch addr.
  25.  
  26. code
  27. ABS=0,        RAN=1,        REM=2,        RESERVE=3,
  28. SWAP=4,        EXTEND=5,    RESTART=6,    CHIN=7,
  29. CHOUT=8,    CRLF=9,        INTIN=10,    INTOUT=11,
  30. TEXT=12,    OPENI=13,    OPENO=14,    CLOSE=15,
  31. ABORT=16    HEXIN=26,    HEXOUT=27,    SWAP_W=117,
  32. EXT_L=118,    GETKEY=125;
  33.  
  34. def    TV=0, KB=0;
  35. def    TAB=$09, BEL=$07, CR=$0D, LF=$0A, ESC=$1B;
  36.  
  37. addr    BASE;        \Base address of PC (usually = 0)
  38. int    II,        \Scratch
  39.     DEV,        \Output device number
  40.     PC,        \Program Counter
  41.     OP,        \16-bit opcode
  42.     DSTREG,        \3-bit destination register field of OP
  43.     DSTMODE,    \3-bit destination mode field
  44.     SRCMODE,    \3-bit source mode field
  45.     SRCREG,        \3-bit source register
  46.     SIZE,        \2-bit size field (0=B, 1=W, 2=L)
  47.     CC,        \4-bit condition code field
  48.     CC1,CC2,    \Condition code letters
  49.     BIT,        \Table of bit positions
  50.     LINEPTR,    \Pointer into LINEBUF
  51.     ASCPTR,        \Pointer into ASCII field
  52.     HEXPTR,        \Pointer into hex field
  53.     TXTPTR;        \Pointer into text field
  54. def    LINEMAX=79;    \Last byte of LINEBUF
  55. addr    LINEBUF,    \Line buffer
  56.     HEXTBL,        \Hex table
  57.     CCSTR;        \String array containing all condition codes
  58.  
  59. \----------------------------------------------------------------------\
  60.  
  61. proc    CHARO(CH);    \Write char to line buffer
  62. int    CH;
  63. begin
  64. LINEBUF(LINEPTR):= CH;
  65. if LINEPTR<LINEMAX then LINEPTR:= LINEPTR+1;
  66. end;    \CHARO
  67.  
  68.  
  69.  
  70. proc    CHO(CH);    \Write char to text field
  71. int    CH;
  72. begin
  73. LINEPTR:= TXTPTR;
  74. CHARO(CH);
  75. TXTPTR:= LINEPTR;
  76. end;    \CHO
  77.  
  78.  
  79.  
  80. proc    CRO;        \Write CR LF to text field
  81. begin
  82. CHO(CR);
  83. end;    \CRO
  84.  
  85.  
  86.  
  87. proc    TXT(STR);    \Write string to text field
  88. addr    STR;
  89. int    I;
  90. begin
  91. LINEPTR:= TXTPTR;
  92. loop for I:= 0,32767 do
  93.     begin
  94.     if STR(I) = 0 then quit;
  95.     CHARO(STR(I));
  96.     end;
  97. TXTPTR:= LINEPTR;
  98. end;    \TXT
  99.  
  100.  
  101.  
  102. proc    NUMO(N);    \Write signed, 16-bit decimal integer to text field
  103. int    N;
  104. int    I,X,ZEROFL,TENPWR;
  105. begin
  106. LINEPTR:= TXTPTR;
  107. N:= EXT_L(N);
  108. if N<0 then [N:= -N; CHARO(^-)];
  109.  \(Note that with 32-bit XPL, a 16-bit integer will never appear negative.)
  110. TENPWR:= 10000;
  111. ZEROFL:= 0;
  112. for I:= 0,3 do
  113.     begin
  114.     X:= N/TENPWR;
  115.     N:= REM(0);
  116.     ZEROFL:= ZEROFL ! X;
  117.     if ZEROFL then CHARO(X+^0);
  118.     TENPWR:= TENPWR/10;
  119.     end;
  120. CHARO(N+^0);
  121. TXTPTR:= LINEPTR;
  122. end;    \NUMO
  123.  
  124.  
  125.  
  126. proc    HEXB(N);    \Write hex byte to line buffer
  127. int    N;
  128. begin
  129. CHARO(HEXTBL((N&$FF)/$10));
  130. CHARO(HEXTBL(REM(0)));
  131. end;    \HEXB
  132.  
  133.  
  134.  
  135. proc    HEXW(N);    \Write hex word to line buffer
  136. int    N;
  137. begin
  138. HEXB(SWAP(N));
  139. HEXB(N);
  140. end;    \HEXW
  141.  
  142.  
  143.  
  144. proc    HEXO(N);    \Write hex word to text field
  145. int    N;
  146. begin
  147. LINEPTR:= TXTPTR;
  148. HEXW(N);
  149. TXTPTR:= LINEPTR;
  150. end;    \HEXO
  151.  
  152.  
  153.  
  154. proc    ASCO(N);    \Write ASCII-dump char to line buffer
  155. int    N;
  156. int    CH;
  157. begin
  158. CH:= N&$7F;
  159. if CH<$20 ! CH=$7F then CH:= ^.;
  160. CHARO(CH);
  161. end;    \ASCO
  162.  
  163.  
  164.  
  165. proc    DUMP(N);    \Write hex- and ASCII-dump to line buffer
  166. int    N;
  167. begin
  168. LINEPTR:= HEXPTR;
  169. HEXW(N);
  170. HEXPTR:= LINEPTR;
  171.  
  172. LINEPTR:= ASCPTR;
  173. ASCO(SWAP(N));
  174. ASCO(N);
  175. ASCPTR:= LINEPTR;
  176. end;    \DUMP
  177.  
  178.  
  179.  
  180. proc    GETOP;        \Get opcode at PC and bump PC
  181. begin
  182. \Note that the 6502 and the 68000 order high and low bytes differently.
  183. OP:= SWAP(BASE(PC)) + BASE(PC+1);
  184. DUMP(OP);
  185. PC:= PC +2;
  186. end;    \GETOP
  187.  
  188. \----------------------------------------------------------------------\
  189.  
  190. proc    D(REG);        \Output data register
  191. int    REG;
  192. begin
  193. CHO(^D); NUMO(REG);
  194. end;    \D
  195.  
  196.  
  197.  
  198. proc    A(REG);        \Output address register
  199. int    REG;
  200. begin
  201. if REG=7 then TXT("SP")
  202. else [CHO(^A); NUMO(REG)];
  203. end;    \A
  204.  
  205.  
  206.  
  207. proc    DOMODE(MODE, REG);    \Output effective address
  208. int    MODE, REG;
  209. begin
  210. case MODE of
  211.   $0:    D(REG);                        \Dn
  212.   $1:    A(REG);                        \An
  213.   $2:    [CHO(^(); A(REG); CHO(^))];            \(An)
  214.   $3:    [CHO(^(); A(REG); TXT(")+")];            \(An)+
  215.   $4:    [TXT("-("); A(REG); CHO(^))];            \-(An)
  216.   $5:    [GETOP; NUMO(OP); CHO(^(); A(REG); CHO(^))];    \d(An)
  217.   $6:    [GETOP; NUMO(EXTEND(OP&$00FF));            \d(An,Xi)
  218.     CHO(^(); A(REG); CHO(^,);
  219.     CHO(if OP&$8000 then ^A else ^D); NUMO((OP&$7000)/$1000);
  220.     CHO(^.); CHO(if OP&$0800 then ^L else ^W); CHO(^))];
  221.   $7:    case REG of
  222.       0:    [GETOP; CHO(^$); HEXO(OP); TXT(".W")];        \Abs.W
  223.       1:    [GETOP; CHO(^$); HEXO(OP); GETOP; HEXO(OP); TXT(".L")];    \Abs.L
  224.       2:    [GETOP; CHO(^$); HEXO(SWAP_W(EXT_L(OP)+PC-2));
  225.         HEXO(OP+PC-2); TXT("(PC)")];            \d(PC)
  226.       3:    [GETOP; CHO(^$); HEXO(PC-2+(EXTEND(OP&$00FF)));    \d(PC,Xi)
  227.         TXT("(PC,");
  228.         CHO(if OP&$8000 then ^A else ^D); NUMO((OP&$7000)/$1000);
  229.         CHO(^.); CHO(if OP&$0800 then ^L else ^W); CHO(^))];
  230.       4:    [TXT("#$");                    \Imm
  231.         GETOP;
  232.         case SIZE of
  233.           0:    HEXO(OP);    \(not sign extended)
  234.           1:    HEXO(OP);
  235.           2:    [HEXO(OP); GETOP; HEXO(OP)]
  236.         other TXT("???")]
  237.     other    TXT("???")
  238. other;
  239. end;    \DOMODE
  240.  
  241.  
  242.  
  243. proc    DST;        \Destination effective address
  244. begin
  245. DOMODE(DSTMODE, DSTREG);
  246. end;    \DST
  247.  
  248.  
  249.  
  250. proc    SRC;        \Source effective address
  251. begin
  252. DOMODE(SRCMODE, SRCREG);
  253. end;    \SRC
  254.  
  255.  
  256.  
  257. proc    SIZEXT;        \Output size extension
  258. begin
  259. CHO(^.);
  260. case SIZE of
  261.   0:    CHO(^B);
  262.   1:    CHO(^W);
  263.   2:    CHO(^L)
  264. other    CHO(^?);
  265. CHO(TAB);
  266. end;    \SIZEXT
  267.  
  268.  
  269.  
  270. func    REVERSE(N);    \Reverse the order of the bits in N
  271. int    N;
  272. int    I, M;
  273. begin
  274. M:= 0;
  275. for I:= 0,15 do
  276.     if BIT(I) & N then M:= M ! BIT(15-I);
  277. return    M;
  278. end;    \REVERSE
  279.  
  280.  
  281.  
  282. proc    SHOWREGS(MASK);        \Show the registers defined by MASK
  283. int    MASK;            \Order from MSB to LSB: A7-A0/D7-D0
  284. int    I, HIT, RUN, FIRST;
  285.  
  286.  
  287.  
  288. proc    SREGS(MASK, R);        \Show data or address registers
  289. int    MASK, R;
  290. begin
  291. HIT:= false;
  292. RUN:= false;
  293. for I:= 0,7 do
  294.     begin
  295.     if BIT(I) & MASK then        \Bit is set
  296.         begin
  297.         if HIT then RUN:= true
  298.         else    [if FIRST then FIRST:= false else CHO(^/);
  299.             CHO(R); NUMO(I); HIT:= true];
  300.         end
  301.     else    begin            \Bit is clear
  302.         if RUN then [CHO(^-); CHO(R); NUMO(I-1)];
  303.         HIT:= false;
  304.         RUN:= false;
  305.         end;
  306.     end;
  307. if RUN then [CHO(^-); CHO(R); NUMO(7)];
  308. end;    \SREGS
  309.  
  310.  
  311.  
  312. begin    \SHOWREGS
  313. FIRST:= true;
  314. SREGS(MASK, ^D);
  315. SREGS(SWAP(MASK), ^A);
  316. end;    \SHOWREGS
  317.  
  318.  
  319.  
  320. proc    MOVEMOP;    \Generate a MOVEM instruction, e.g: MOVEM. D1-D7,64(A0)
  321. begin
  322. TXT("MOVEM");
  323. SIZEXT;
  324. GETOP;
  325. SHOWREGS(if SRCMODE=4 then REVERSE(OP) else OP);
  326. CHO(^,);
  327. SRC;
  328. end;    \MOVEMOP
  329.  
  330.  
  331.  
  332. proc    TWOOP;        \Decoding for two operands
  333. \This is correct for ADD & SUB, the most general case, other
  334. \ operators should do their exceptions first.
  335. begin
  336. case DSTMODE of
  337.   $0:    [TXT(".B    "); SRC; CHO(^,); D(DSTREG)];
  338.   $1:    [TXT(".W    "); SRC; CHO(^,); D(DSTREG)];
  339.   $2:    [TXT(".L    "); SRC; CHO(^,); D(DSTREG)];
  340.   $3:    [TXT("A.W    "); SRC; CHO(^,); A(DSTREG)];
  341.   $4:    [TXT(".B    "); D(DSTREG); CHO(^,); SRC];
  342.   $5:    [TXT(".W    "); D(DSTREG); CHO(^,); SRC];
  343.   $6:    [TXT(".L    "); D(DSTREG); CHO(^,); SRC];
  344.   $7:    [TXT("A.L    "); SRC; CHO(^,); A(DSTREG)]
  345. other;
  346. end;    \TWOOP
  347.  
  348.  
  349.  
  350. proc    IMMOP;        \Group $0000
  351.  
  352.  
  353.     proc    IMM(STR);
  354.     addr    STR;
  355.     begin
  356.     TXT(STR);
  357.     if SRCMODE=7 & SRCREG=4 then
  358.         begin
  359.         TXT("    #$"); GETOP; HEXO(OP);
  360.         if OP&$0040 then TXT(",SR") else TXT(",CCR");
  361.         end
  362.     else    [SIZEXT; TXT("#$"); GETOP; HEXO(OP);
  363.         if SIZE=2 then [GETOP; HEXO(OP)];    \Long
  364.         CHO(^,); SRC];
  365.     end;    \IMM
  366.  
  367.  
  368. begin    \IMMOP
  369. if OP&$0100 then
  370.     begin
  371.     if SRCMODE=1 then
  372.         [TXT("MOVEP.");
  373.         case SIZE of
  374.           0:    [TXT("W    "); GETOP; NUMO(OP); CHO(^();
  375.             A(SRCREG); TXT("),"); D(DSTREG)];
  376.           1:    [TXT("L    "); GETOP; NUMO(OP); CHO(^();
  377.             A(SRCREG); TXT("),"); D(DSTREG)];
  378.           2:    [TXT("W    "); D(DSTREG); CHO(^,);
  379.             GETOP; NUMO(OP); CHO(^(); A(SRCREG); CHO(^))];
  380.           3:    [TXT("L    "); D(DSTREG); CHO(^,);
  381.             GETOP; NUMO(OP); CHO(^(); A(SRCREG); CHO(^))]
  382.         other;
  383.         ]
  384.     else    [case SIZE of        \Dynamic bit ops
  385.           0:    TXT("BTST");
  386.           1:    TXT("BCHG");
  387.           2:    TXT("BCLR");
  388.           3:    TXT("BSET")
  389.         other;
  390.         SIZE:= 2;        \Size = long only
  391.         TXT("    "); D(DSTREG); CHO(^,); SRC;
  392.         ];
  393.     end
  394. else    begin
  395.     case DSTREG of
  396.       0:    IMM("ORI");
  397.       1:    IMM("ANDI");
  398.       2:    IMM("SUBI");
  399.       3:    IMM("ADDI");
  400.       4:    [case SIZE of
  401.           0:    TXT("BTST");
  402.           1:    TXT("BCHG");
  403.           2:    TXT("BCLR");
  404.           3:    TXT("BSET")
  405.         other;
  406.         SIZE:= 0;        \Size = byte only
  407.         TXT("    #"); GETOP; NUMO(OP&$007F); CHO(^,); SRC;
  408.         ];
  409.       5:    IMM("EORI");
  410.       6:    IMM("CMPI");
  411.       7:    [TXT("MOVES"); SIZEXT; CHO(^$); GETOP; HEXO(OP)]
  412.     other;
  413.     end;
  414. end;    \IMMOP
  415.  
  416.  
  417.  
  418. proc    MOVEOP;        \Generate a MOVE instruction ($1000, $2000, $3000)
  419. begin
  420. TXT("MOVE");
  421. if DSTMODE=1 then CHO(^A);
  422. SIZEXT;
  423. SRC; CHO(^,); DST;
  424. end;    \MOVEOP
  425.  
  426.  
  427.  
  428. proc    NEGXOP;        \Group $4000
  429. int    SOP;
  430. begin
  431. case DSTMODE of
  432.  6:    [SIZE:= 1; TXT("CHK    "); SRC; CHO(^,); D(DSTREG)];
  433.  7:    [TXT("LEA    "); SRC; CHO(^,); A(DSTREG)]
  434. other begin
  435. case DSTREG of
  436.  0:    if SIZE=3 then [SIZE:= 1; TXT("MOVE    SR,"); SRC]
  437.     else [TXT("NEGX"); SIZEXT; SRC];
  438.  1:    if SIZE=3 then [SIZE:= 1; TXT("MOVE    CCR,"); SRC]
  439.     else [TXT("CLR"); SIZEXT; SRC];
  440.  2:    if SIZE=3 then [SIZE:= 1; TXT("MOVE    "); SRC; TXT(",CCR")]
  441.     else [TXT("NEG"); SIZEXT; SRC];
  442.  3:    if SIZE=3 then [SIZE:= 1; TXT("MOVE    "); SRC; TXT(",SR")]
  443.     else [TXT("NOT"); SIZEXT; SRC];
  444.  4:    case DSTMODE of
  445.      0:    [TXT("NBCD    "); SRC];
  446.      1:    if SRCMODE=0 then [TXT("SWAP    "); D(SRCREG)]
  447.         else    [TXT("PEA    "); SRC];
  448.      2:    if SRCMODE=0 then [TXT("EXT.W    "); D(SRCREG)]
  449.         else    [SIZE:= 1; MOVEMOP];
  450.      3:    if SRCMODE=0 then [TXT("EXT.L    "); D(SRCREG)]
  451.         else    [SIZE:= 2; MOVEMOP]
  452.     other    TXT("???");
  453.  5:    if SIZE=3 then
  454.         begin
  455.         if SRCMODE=7 then TXT("ILLEGAL")
  456.         else [SIZE:= 0; TXT("TAS    "); SRC];
  457.         end
  458.     else [TXT("TST"); SIZEXT; SRC];
  459.  6:    [TXT("MOVEM."); CHO(if OP&$0040 then ^L else ^W); CHO(TAB);
  460.     GETOP; SOP:= OP; SRC; CHO(^,); SHOWREGS(SOP)];
  461.     \(Register bits won't need reversing because predecrement is not allowed)
  462.  7:    begin
  463.     case DSTMODE of
  464.      1:    begin
  465.         case SRCMODE of
  466.          0,1:    [TXT("TRAP    #"); NUMO(OP&$000F)];
  467.          2:    [TXT("LINK    "); A(SRCREG); TXT(",#");
  468.             GETOP; NUMO(OP)];
  469.          3:    [TXT("UNLK    "); A(SRCREG)];
  470.          4:    [TXT("MOVE    "); A(SRCREG); TXT(",USP")];
  471.          5:    [TXT("MOVE    USP,"); A(SRCREG)];
  472.          6:    begin
  473.             case SRCREG of
  474.              0:    TXT("RESET");
  475.              1:    TXT("NOP");
  476.              2:    TXT("STOP");
  477.              3:    [TXT("RTE"); CRO];
  478.              4:    [TXT("RTD"); CRO];
  479.              5:    [TXT("RTS"); CRO];
  480.              6:    TXT("TRAPV");
  481.              7:    [TXT("RTR"); CRO]
  482.             other;
  483.             end;
  484.          7:    TXT("MOVEC")
  485.         other;
  486.         end;
  487.      2:    [TXT("JSR    "); SRC];
  488.      3:    [TXT("JMP    "); SRC; CRO]
  489.     other    TXT("???");
  490.     end
  491. other;
  492. end;
  493. end;    \NEGXOP
  494.  
  495.  
  496.  
  497. proc    ADDQOP;        \Group $5000: ADDQ, SCC, DBCC, SUBQ
  498.  
  499.  
  500.     proc    QUICK(STR);
  501.     addr    STR;
  502.     begin
  503.     TXT(STR);
  504.     SIZEXT;
  505.     CHO(^#); NUMO(if DSTREG=0 then 8 else DSTREG); CHO(^,);
  506.     SRC;
  507.     end;    \QUICK
  508.  
  509.  
  510. begin    \ADDQOP
  511. case DSTMODE of
  512.   $0,$1,$2:    QUICK("ADDQ");
  513.   $3,$7:    if SRCMODE=1 then
  514.             begin
  515.             TXT("DB"); CHO(CC1); CHO(CC2);
  516.             CHO(TAB); D(SRCREG);
  517.             CHO(^,); GETOP; CHO(^$);
  518.             HEXO(SWAP_W(EXT_L(OP)+PC-2));
  519.             HEXO(OP+PC-2);
  520.             end
  521.         else    begin
  522.             CHO(^S); CHO(CC1); CHO(CC2);
  523.             CHO(TAB); SRC;
  524.             end;
  525.   $4,$5,$6:    QUICK("SUBQ")
  526. other;
  527. end;    \ADDQOP
  528.  
  529.  
  530.  
  531. proc    BRAOP;        \Generate branch instructions (group $6000)
  532. int    DISP;
  533. begin
  534. case CC of
  535.   0:    [TXT("BRA")];            \Do the exceptions first
  536.   1:    [TXT("BSR")]
  537. other    [CHO(^B); CHO(CC1); CHO(CC2)];
  538. DISP:= OP&$00FF;
  539. if DISP=0 then [TXT(".L    $"); GETOP; HEXO(SWAP_W(EXT_L(OP)+PC-2)); HEXO(OP+PC-2)]
  540. else [TXT(".S    $"); HEXO(SWAP_W(EXT_L(EXTEND(DISP))+PC)); HEXO(EXTEND(DISP)+PC)];
  541. if CC=0 then CRO;
  542. end;    \BRAOP
  543.  
  544.  
  545.  
  546. proc    OROP;        \Group $8000
  547. begin
  548. if DSTMODE=4 & SRCMODE=0 then
  549.     [TXT("SBCD    "); D(SRCREG); CHO(^,); D(DSTREG)]
  550. else if DSTMODE=4 & SRCMODE=1 then
  551.     [TXT("SBCD    "); TXT("-("); A(SRCREG);
  552.     TXT("),-("); A(DSTREG); CHO(^))]
  553. else case DSTMODE of
  554.   3:    [TXT("DIVU"); CHO(TAB); SRC; CHO(^,); D(DSTREG)];
  555.   7:    [TXT("DIVS"); CHO(TAB); SRC; CHO(^,); D(DSTREG)]
  556. other    [TXT("OR"); TWOOP];
  557. end;    \OROP
  558.  
  559.  
  560.  
  561. proc    SUBOP;        \Group $9000
  562. begin
  563. TXT("SUB");
  564. TWOOP;
  565. end;    \SUBOP
  566.  
  567.  
  568.  
  569. proc    CMPOP;        \Group $B000
  570. begin
  571. case DSTMODE of 4,5,6:
  572.     if SRCMODE=1 then
  573.         [TXT("CMPM"); SIZEXT; CHO(^();
  574.         A(SRCREG); TXT(")+,("); A(DSTREG); TXT(")+")]
  575.     else [TXT("EOR"); TWOOP]
  576. other [TXT("CMP"); TWOOP];
  577. end;    \CMPOP
  578.  
  579.  
  580.  
  581. proc    ANDOP;        \Group $C000
  582. begin
  583. case of
  584.    DSTMODE=5 & SRCMODE=0:    [TXT("EXG    "); D(SRCREG);
  585.                 CHO(^,); D(DSTREG)];
  586.    DSTMODE=5 & SRCMODE=1:    [TXT("EXG    "); A(SRCREG);
  587.                 CHO(^,); A(DSTREG)];
  588.    DSTMODE=6 & SRCMODE=1:    [TXT("EXG    "); A(SRCREG);
  589.                 CHO(^,); D(DSTREG)];
  590.    DSTMODE=4 & (SRCMODE&6)=0:    [TXT("ABCD"); TWOOP]
  591. other    case DSTMODE of                        \ABCD,
  592.       3:    [TXT("MULU"); CHO(TAB); SRC; CHO(^,); D(DSTREG)];
  593.       7:    [TXT("MULS"); CHO(TAB); SRC; CHO(^,); D(DSTREG)]
  594.     other    [TXT("AND"); TWOOP];
  595. end;    \ANDOP
  596.  
  597.  
  598.  
  599. proc    ADDOP;        \Group $D000
  600. begin
  601. TXT("ADD");
  602. TWOOP;
  603. end;    \ADDOP
  604.  
  605.  
  606.  
  607. proc    SHIFTOP;    \Group $E000
  608.  
  609.  
  610.     proc    NAME(TYPE);
  611.     int    TYPE;
  612.     begin
  613.     case TYPE of
  614.       0:    TXT("AS");
  615.       1:    TXT("LS");
  616.       2:    TXT("ROX");
  617.       3:    TXT("RO")
  618.     other;
  619.     CHO(if OP&$0100 then ^L else ^R);
  620.     end;    \NAME
  621.  
  622.  
  623. begin
  624. case SIZE of
  625.  0,1,2:    begin
  626.     NAME((OP&$0018)/$8);
  627.     SIZEXT;
  628.     if OP&$0020 then        \I/R field
  629.         [D(DSTREG)]
  630.     else    [CHO(^#); NUMO(if DSTREG=0 then 8 else DSTREG)];
  631.     CHO(^,);
  632.     D(SRCREG);
  633.     end;
  634.  3:    begin
  635.     SIZE:= 1;        \Shift memory, size = word only
  636.     NAME((OP&$0300)/$200);
  637.     CHO(TAB);
  638.     SRC;
  639.     end
  640. other;
  641. end;    \SHIFTOP
  642.  
  643. \----------------------------------------------------------------------\
  644.  
  645. proc    FLINE;        \Group $F000, 68881 instructions
  646. int    K, FDSTREG, FSRCREG;
  647.  
  648.  
  649.  
  650. proc    FMT(F);        \Output the field specifier
  651. int    F;
  652. addr    STR;
  653. begin
  654. CHO(^.);
  655. STR:= "LSXPWDBP ";
  656. CHO(STR(F));
  657. end;    \FMT
  658.  
  659.  
  660.  
  661.  
  662. proc    FP(REG);    \Output the floating-point register
  663. int    REG;
  664. begin
  665. TXT("FP"); NUMO(REG);
  666. end;    \FP
  667.  
  668.  
  669.  
  670.  
  671. proc    DOFOP(STR);    \Disassemble common floating-point opcodes
  672. addr    STR;
  673. int    FSRCREG, FDSTREG;
  674. begin
  675. TXT(STR);
  676. FSRCREG:= (OP & $1C00) /$400;
  677. FDSTREG:= (OP & $0380) /$80;
  678.  
  679. if OP & $4000 then            \Test R/M bit
  680.     begin                \FABS<fmt>  <ea>,FPn
  681.     FMT(FSRCREG); CHO(TAB); SRC; CHO(^,); FP(FDSTREG);
  682.     end
  683. else    begin                \The operation is register to register
  684.     TXT(".X    "); FP(FSRCREG);
  685.     if FSRCREG#FDSTREG then        \FABS.X  FPm,FPn
  686.         [CHO(^,); FP(FDSTREG)];
  687.     end;
  688. end;    \DOFOP;
  689.  
  690.  
  691.  
  692. proc    DOMOVCR;    \FMOVECR  #$xx,FPn
  693. begin
  694. TXT("FMOVECR    #$");
  695. HEXO(OP&$7F);
  696. CHO(^,);
  697. FP((OP&$0380)/$80);
  698. end;    \DOMOVCR
  699.  
  700.  
  701.  
  702. proc    DOFCC;        \Output the condition code
  703. int    I, FCC;
  704. begin
  705. I:= OP & $3F;
  706. if I<=$20 then
  707.     begin
  708.     FCC:=     ["F", "EQ", "OGT", "OGE", "OLT", "OLE", "OGL", "OR",
  709.         "UN", "UEQ", "UGT", "UGE", "ULT", "ULE", "NE", "T",
  710.         "SF", "SEQ", "GT", "GE", "LT", "LE", "GL", "GLE",
  711.         "NGLE", "NGL", "NLE", "NLT", "NGE", "NGT", "SNE", "ST"];
  712.     TXT(FCC(I));
  713.     end
  714. else    CHO(^?);            \Undefined
  715. end;    \DOFCC
  716.  
  717.  
  718.  
  719. begin    \FLINE
  720. case DSTMODE of                \Bits: 8, 7, & 6
  721.    0:    begin
  722.     GETOP;
  723.     case OP & $E000 of
  724.       $0000,$4000:
  725.         begin
  726.         case OP & $7F of
  727.           $00:    if (OP&$5C00) = $5C00 then DOMOVCR
  728.             else DOFOP("FMOVE");    \Memory-to-register operation
  729.           $01:    DOFOP("FINT");
  730.           $02:    DOFOP("FSINH");
  731.           $03:    DOFOP("FINTRZ");
  732.           $04:    DOFOP("FSQRT");
  733.           $06:    DOFOP("FLOGNP1");
  734.           $08:    DOFOP("FETOXM1");
  735.           $09:    DOFOP("FTANH");
  736.           $0A:    DOFOP("FATAN");
  737.           $0C:    DOFOP("FASIN");
  738.           $0D:    DOFOP("FATANH");
  739.           $0E:    DOFOP("FSIN");
  740.           $0F:    DOFOP("FTAN");
  741.           $10:    DOFOP("FETOX");
  742.           $11:    DOFOP("FTWOTOX");
  743.           $12:    DOFOP("FTENTOX");
  744.           $14:    DOFOP("FLOGN");
  745.           $15:    DOFOP("FLOG10");
  746.           $16:    DOFOP("FLOG2");
  747.           $18:    DOFOP("FABS");
  748.           $19:    DOFOP("FCOSH");
  749.           $1A:    DOFOP("FNEG");
  750.           $1C:    DOFOP("FACOS");
  751.           $1D:    DOFOP("FCOS");
  752.           $1E:    DOFOP("FGETEXP");
  753.           $1F:    DOFOP("FGETMAN");
  754.           \In the following FPm should not = FPn
  755.           $20:    DOFOP("FDIV");
  756.           $21:    DOFOP("FMOD");
  757.           $22:    DOFOP("FADD");
  758.           $23:    DOFOP("FMUL");
  759.           $24:    DOFOP("FSGLDIV");
  760.           $25:    DOFOP("FREM");
  761.           $26:    DOFOP("FSCALE");
  762.           $27:    DOFOP("FSGLMUL");
  763.           $28:    DOFOP("FSUB");
  764.           $38:    DOFOP("FCMP");
  765.           $3A:    DOFOP("FTST")    \FPm is not used and it should be = 0
  766.         other    begin
  767.             \WARNING! order is backwards: SIN, COS
  768.             if (OP&$0078) = $30 then
  769.                 [DOFOP("FSINCOS"); CHO(^:); FP(OP&$0007)];
  770.             end;
  771.         end;
  772.  
  773.       $2000: TXT("???");
  774.  
  775.       $6000: begin            \FMOVE.<fmt>    FPn,<ea>
  776.         TXT("FMOVE");
  777.         FDSTREG:= (OP & $1C00) /$400;
  778.         FSRCREG:= (OP & $0380) /$80;
  779.         FMT(FDSTREG); CHO(TAB); FP(FSRCREG); CHO(^,); SRC;
  780.         if FDSTREG=3 then
  781.             [TXT("{#"); K:= OP&$007F;
  782.             if K>=$40 then K:= K-$80;
  783.             NUMO(K); CHO(^})];
  784.         if FDSTREG=7 then
  785.             [TXT("{D"); NUMO((OP&$70) /$10); CHO(^})];
  786.         end;
  787.  
  788.       $8000: begin            \FMOVE(M)    <ea>,FPcr
  789.         TXT("FMOVE(M)    ");
  790.         SRC;
  791.         FDSTREG:= (OP & $1C00) /$400;
  792.         if FDSTREG&1 then TXT(",FPCR");
  793.         if FDSTREG&2 then TXT(",FPSR");
  794.         if FDSTREG&4 then TXT(",FPIAR")
  795.         end;
  796.  
  797.       $A000: begin            \FMOVE(M)    FPcr,<ea>
  798.         TXT("FMOVE(M)    ");
  799.         FSRCREG:= (OP & $1C00) /$400;
  800.         if FSRCREG&1 then TXT("FPCR,");
  801.         if FSRCREG&2 then TXT("FPSR,");
  802.         if FSRCREG&4 then TXT("FPIAR,");
  803.         SRC;
  804.         end;
  805.  
  806.       $C000: begin            \FMOVEM  <ea>,FPn
  807.         TXT("FMOVEM    ");
  808.         SRC;
  809.         CHO(^,);
  810.         GETOP;            \WARNING! inaccurate
  811.         SHOWREGS( SWAP(REVERSE(OP&$00FF)) );
  812.         end;
  813.  
  814.       $E000: begin            \FMOVEM  FPn,<ea>
  815.         TXT("FMOVEM    ");
  816.         GETOP;            \WARNING! inaccurate
  817.         SHOWREGS( SWAP(REVERSE(OP&$00FF)) );
  818.         CHO(^,);
  819.         SRC;
  820.         end
  821.  
  822.     other;
  823.     end;
  824.  
  825.    1:    begin                \FDBcc, FScc, & FTRAPcc
  826.     case SRCMODE of
  827.        1:    begin            \FDBcc    Dn,<label>
  828.         TXT("FDB");
  829.         GETOP;
  830.         DOFCC;
  831.         CHO(TAB);
  832.         D(SRCREG);
  833.         GETOP;
  834.         HEXO(OP+PC-4);
  835.         end;
  836.        7:    begin            \FTRAPcc
  837.         TXT("FTRAP");        \(do exceptions first)
  838.         GETOP;
  839.         DOFCC;
  840.         case SRCREG of        \Mode field
  841.            2:    [TXT(".W    #$"); GETOP; HEXO(OP)];
  842.            3:    [TXT(".L    #$"); GETOP; HEXO(OP); GETOP; HEXO(OP)]
  843.         other    [TXT("FS"); GETOP; DOFCC; CHO(TAB); SRC];
  844.         end
  845.     other    begin            \FScc    <ea>
  846.         TXT("FS"); GETOP; DOFCC; CHO(TAB); SRC;
  847.         end;
  848.     end;
  849.  
  850.    2:    begin                \FBcc & FNOP (16 bits)
  851.     if (OP & $3F) = 0 then TXT("FNOP")
  852.     else    begin
  853.         TXT("FB"); DOFCC; TXT(".W    $");
  854.         GETOP;
  855.         HEXO(OP+PC-2);        \Show the target address
  856.         end;
  857.     end;
  858.  
  859.    3:    begin                \FBcc (32 bits)
  860.     TXT("FB"); DOFCC; TXT(".L    $");
  861.     GETOP;
  862.     HEXO(OP);            \Show the displacement
  863.     GETOP;
  864.     HEXO(OP);
  865.     end;
  866.  
  867.    4:    begin                \FSAVE
  868.     TXT("FSAVE    ");
  869.     SRC;
  870.     end;
  871.  
  872.    5:    begin                \FRESTORE
  873.     TXT("FRESTORE    ");
  874.     SRC;
  875.     end
  876.  
  877. other    TXT("???");
  878. end;    \FLINE
  879.  
  880. \----------------------------------------------------------------------\
  881.  
  882. proc    LOOKUP;
  883. begin
  884. \Chop the opcode into fields:
  885. DSTREG:= (OP&$0E00) /$200;
  886. DSTMODE:= (OP&$01C0) /$40;
  887. SRCMODE:= (OP&$0038) /$8;
  888. SRCREG:= (OP&$0007);
  889. CC:= (OP&$0F00) /$100;
  890. CCSTR:= "T F HILSCCCSNEEQVCVSPLMIGELTGTLE ";
  891. CC1:= CCSTR(CC*2);
  892. CC2:= CCSTR(CC*2 +1);
  893. SIZE:= (OP&$00C0) /$40;
  894.  
  895. case OP & $F000 of
  896.   $0000:    IMMOP;    \ORI, MOVEP, AND, SUBI, ADDI, EORI, CMPI, MOVES
  897.   $1000:    [SIZE:= 0; MOVEOP];    \MOVE.B
  898.   $2000:    [SIZE:= 2; MOVEOP];    \MOVE.L
  899.   $3000:    [SIZE:= 1; MOVEOP];    \MOVE.W
  900.   $4000:    NEGXOP;            \NEGX, MOVE SR, CHK, LEA, CLR, ... JMP
  901.   $5000:    ADDQOP;            \ADDQ, SCC, DBCC, SUBQ
  902.   $6000:    BRAOP;
  903.   $7000:    [TXT("MOVEQ    #"); NUMO(EXTEND(OP & $FF)); CHO(^,);
  904.         D(DSTREG)];        \MOVEQ
  905.   $8000:    OROP;            \OR, DIV, SBCD
  906.   $9000:    SUBOP;            \SUB
  907.   $A000:    TXT("1010 EMULATOR");    \Line 1010 emulator
  908.   $B000:    CMPOP;            \CMP, EOR
  909.   $C000:    ANDOP;            \AND, MUL ABCD, EXG
  910.   $D000:    ADDOP;            \ADD
  911.   $E000:    SHIFTOP;        \Shift/rotate
  912.   $F000:    FLINE            \68881 line $F emulator
  913. other;
  914. end;    \LOOKUP
  915.  
  916. \----------------------------------------------------------------------\
  917.  
  918. begin    \MAIN
  919. LINEBUF:= RESERVE(LINEMAX+1);
  920. HEXTBL:= "0123456789ABCDEF ";
  921. BIT:= [    $0001, $0002, $0004, $0008, $0010, $0020, $0040, $0080,
  922.     $0100, $0200, $0400, $0800, $1000, $2000, $4000, $8000];
  923.  
  924. TEXT(TV,"-- 68000/68881 DISASSEMBLER, V1.1x3 --
  925.  
  926. PRESS ^"ESC^" TO RESTART THIS PROGRAM.
  927. PRESS ANY KEY TO DISASSEMBLE A LINE.
  928. ");
  929. loop    begin
  930.     CRLF(TV);
  931.     TEXT(TV,"OUTPUT DEVICE (0-7)? ");
  932.     DEV:= INTIN(KB);
  933.     TEXT(TV,"ADDRESS? $");        \Get start address
  934.     PC:= HEXIN(KB);
  935.  
  936.     OPENO(DEV);
  937.     BASE:= 0;
  938.     loop    begin
  939.         ASCPTR:= 0;        \Initialize line buffer pointers
  940.         HEXPTR:= 23;
  941.         TXTPTR:= 45;
  942.         for II:= 0,TXTPTR-1 do LINEBUF(II):= ^ ;    \Init line buffer
  943.         LINEPTR:= 12;        \Output 32-bit PC value
  944.  
  945.         HEXW(SWAP_W(PC));    \Output high 16 bits
  946.         HEXW(PC);        \Output low 16 bits
  947.         CHARO(^:);
  948.  
  949.         GETOP;            \Get word from memory
  950.         LOOKUP;
  951.  
  952.         CRO;
  953.  
  954.         \Dump line buffer to output device:
  955.         for II:= 0,TXTPTR-1 do CHOUT(DEV,LINEBUF(II));
  956.         II:= GETKEY;
  957.         case II of
  958.           ESC:    quit;
  959.           $03:    exit;        \CTRL-C
  960.           $10:    ABORT        \CTRL-P
  961.         other;            \do the loop
  962.         end;
  963.     CLOSE(DEV);
  964.     end;
  965. end;    \MAIN
  966. SC: